package com.turingoal.license.checker;

import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.resource.ResourceUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Base64;

/**
 * 工具类-》基础工具类-》License工具类
 * <p>
 * [依赖 License3j]
 * </p>
 */
public final class TgLicenseCheckUtil {
    private static Logger logger = LoggerFactory.getLogger("licensej校验"); // 平台日志

    private TgLicenseCheckUtil() {
        throw new Error("工具类不能实例化！");
    }

    /**
     * 读取license
     */
    static TgLicense readLicense(final String filePath, final byte[] header) {
        TgLicense license = new TgLicense();
        File file = new File(filePath);
        if (file.exists()) {
            license = readLicense(file, header);
        } else {
            try {
                license = readLicense(ResourceUtil.getStreamSafe(filePath), header);
            } catch (IORuntimeException e) {
                logger.debug("*************** license文件不存在 ***************");
            }
        }
        return license;
    }

    /**
     * 读取license
     */
    static TgLicense readLicense(final File licenseFile, final byte[] header) {
        TgLicense license = null;
        if (licenseFile.exists()) {
            try {
                license = readLicense(new FileInputStream(licenseFile), header);
            } catch (FileNotFoundException e) {
                logger.debug("*************** license文件不存在 ***************");
            }
        }
        return license;
    }

    /**
     * 读取license
     */
    static TgLicense readLicense(final InputStream licenseIs, final byte[] header) {
        TgLicense license = new TgLicense();
        if (licenseIs != null) {
            byte[] bytes = TgLicenseUtil.readBytes(licenseIs); // 原始文件数据
            if (bytes != null) {
                license.setExist(true); // 文件存在
                if (bytes.length > 0) {
                    byte[] base64Bytes = null; // 序列化后base64编码的数据
                    if (header != null && header.length > 0) { // 有头部文件，去掉头
                        byte[] fileHeader = new byte[header.length]; // 文件头
                        System.arraycopy(bytes, 0, fileHeader, 0, header.length);
                        if (!Arrays.equals(header, fileHeader)) {  // 文件头不正确
                            license.setOk(false); // 不合法
                            logger.error("*************** license文件不合法 ***************");
                            return license;
                        } else { // 文件头正确，去掉头
                            base64Bytes = new byte[bytes.length - header.length];
                            System.arraycopy(bytes, header.length, base64Bytes, 0, bytes.length - header.length);
                        }
                    } else { // 没有文件头
                        base64Bytes = bytes;
                    }
                    if (base64Bytes.length > 0) {
                        byte[] encryptedDataWithPublicKey;
                        try {
                            encryptedDataWithPublicKey = Base64.getDecoder().decode(base64Bytes); // base64解码
                        } catch (IllegalArgumentException e) {
                            logger.error("*************** license文件不合法 ***************");
                            return license;
                        }
                        if (encryptedDataWithPublicKey != null && encryptedDataWithPublicKey.length > 294) {
                            byte[] publicKey = new byte[294]; // 公钥，长度294
                            System.arraycopy(encryptedDataWithPublicKey, 0, publicKey, 0, 294);
                            byte[] encryptedData = new byte[encryptedDataWithPublicKey.length - 294]; // 加密后数据
                            System.arraycopy(encryptedDataWithPublicKey, 294, encryptedData, 0, encryptedDataWithPublicKey.length - 294);
                            byte[] objBytes = TgLicenseDecryptUtil.decryptByPublicKey(encryptedData, publicKey); // 解密
                            if (objBytes != null) {
                                TgLicense lic = TgLicenseUtil.deserialize(objBytes);
                                if (lic == null) { // 序列化失败
                                    logger.error("*************** license文件不合法 ***************");
                                    return license;
                                } else {
                                    license = lic;
                                    license.setExist(true);
                                    license.setOk(true); // 合法
                                    return license;
                                }
                            } else { // 解密失败
                                logger.debug("*************** license文件不合法 ***************");
                            }
                        } else { // 没有公钥或公钥长度不够
                            logger.debug("*************** license文件不合法 ***************");
                        }
                    } else { // 除了头没有内容
                        logger.debug("*************** license文件不合法 ***************");
                    }
                } else {
                    logger.debug("*************** license文件为空 ***************");
                }
            } else {
                logger.debug("*************** license文件不存在 ***************");
            }
        } else {
            logger.debug("*************** license文件不存在 ***************");
        }
        return license;
    }
}
